﻿Shader "Running/Terrain_1pass" {
	Properties {
		 _Control ("Control (RGBA)", 2D) = "red" {}
		 _Splat3 ("Layer 3 (A)", 2D) = "white" {}
		 _Splat2 ("Layer 2 (B)", 2D) = "white" {}
		 _Splat1 ("Layer 1 (G)", 2D) = "white" {}
		 _Splat0 ("Layer 0 (R)", 2D) = "white" {}

		 _FuckTex("FuckTexture", 2D) = "white" {}
		 _outlineColor2("outlineColor2", Color) = (1, 1, 1, 1)
		 _outlineColor3("outlineColor3", Color) = (1, 1, 1, 1)
		 _outlineColor4("outlineColor4", Color) = (1, 1, 1, 1)
		 _outlineColor5("outlineColor5", Color) = (1, 1, 1, 1)

		 _isolineParams("isolineParams", Vector) = (1, 1, 1, 1)

		 _gradientMap("gradientMap", 2D) = "white" {}
		 _ambientLightColor("_ambientLightColor", Color) = (1, 1, 1, 1)

		 _shadowMap("shadowMap", 2D) = "white" {}

		inverseShadowmapSize("inverseShadowmapSize", Float) = 1
		fixedDepthBias("fixedDepthBias", Float) = 0
		gradientClamp("gradientClamp", Float) = 0
		gradientScaleBias("gradientScaleBias", Float) = 1

		 shadowColor("shadowColor", Color) = (0, 0, 0, 1)

	}

	Category {
		Tags {
			"Queue" = "Geometry-99"
			"IgnoreProjector"="True"
			"RenderType" = "Opaque"
		}



		SubShader { 
			Tags {
					"NormalDepthRender" = "Terrain"
			}
			pass {
				Name "FORWARD"
				Tags { 
					"LightMode" = "ForwardBase" 
				}
				Lighting Off

				CGPROGRAM
				#pragma vertex vert_surf
				#pragma fragment frag_surf
				#pragma multi_compile_fwdbase

				#include "UnityCG.cginc"
				#include "Lighting.cginc"
				#include "TerrainSplatmapCommon.cginc"
				#include "tools.cginc"

				//泥土纹理
				sampler2D _FuckTex;

				struct v2f_surf {
			        float4 pos : SV_POSITION;
			  		float4 pack0 : TEXCOORD0; // _Splat0 _Splat1  //outDecal1AndDecal2UV
			  		float4 pack1 : TEXCOORD1; // _Splat2 _Splat3  //outDecal3AndDecal4UV
			  		float2 custompack0 : TEXCOORD2; //_ControlMap
					float4 outAlphaUVAndHeight : TEXCOORD3; //alpha xy and height zw
					//float2 outDecal5UV : TEXCOORD4;
					float4 outDiffuseLightColor : TEXCOORD4;
					float4 shadowUV : TEXCOORD5;
			    };

			    struct SurfaceOutput2 {
					fixed3 Albedo;
					fixed Alpha;
				};

			    float4 _Splat0_ST;
				float4 _Splat1_ST;
				float4 _Splat2_ST;
				float4 _Splat3_ST;
				/*
				float4 lightning(float4 lightPosition, float4 lightColour, float4 worldPos, float4x4 worldIT, float3 normal) {
					float3 worldNorm = mul(worldIT, normal).xyz;
					float3 lightDir = normalize(
						lightPosition.xyz - (worldPos.xyz * lightPosition.w));
					return lightColour * max(dot(lightDir, worldNorm), 0.0);
				}
				*/
				//uniform float4x4 texViewProj;

				v2f_surf vert_surf (appdata_full v) {
				  v2f_surf o;
				  UNITY_INITIALIZE_OUTPUT(v2f_surf,o);
				  float4 worldPos = mul(unity_ObjectToWorld, v.vertex);

				  Input customInputData;
				  //SplatmapVert (v, customInputData);
				  customInputData.tc_Control = TRANSFORM_TEX(v.texcoord, _Control);
				  o.custompack0.xy = customInputData.tc_Control;

				  //o.pos = UnityObjectToClipPos(v.vertex);
				  o.pos = mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, v.vertex));
				  o.outAlphaUVAndHeight.xy = TRANSFORM_TEX(v.texcoord, _Control); //纹理坐标
				  o.outAlphaUVAndHeight.z = v.vertex.y - 0.1; //地形相对高度
				  o.outAlphaUVAndHeight.w = v.normal.y;// 地形法向Y 方向

				  o.pack0.xy = TRANSFORM_TEX(v.texcoord, _Splat0);
				  o.pack0.zw = TRANSFORM_TEX(v.texcoord, _Splat1);
				  o.pack1.xy = TRANSFORM_TEX(v.texcoord, _Splat2);
				  o.pack1.zw = TRANSFORM_TEX(v.texcoord, _Splat3);

				  //没有non uniform scale 计算normal
				  o.outDiffuseLightColor = lightning(_WorldSpaceLightPos0, _LightColor0, worldPos, unity_WorldToObject, v.normal);
				  o.shadowUV = mul(texViewProj, worldPos);
				  return o;
				}


				fixed4 splatAlphaBlend(fixed4 current, sampler2D decalMap, fixed2 uv, fixed alpha) {
					fixed4 color = tex2D(decalMap, uv);
					//fixed realAlpha = alpha;
					//fixed4 baseCol = (1-realAlpha) * current  + realAlpha * imgCol ;
					return (1.0 - alpha) * current + alpha * color;
					//return baseCol;
				}

				fixed4 alphaOutline2(fixed alpha, fixed4 baseColor, fixed4 outlineColor, fixed4 current) {
					float4 oColor;
					const float OUTLINE_MIN_VALUE0 = 0.450;
					const float OUTLINE_MIN_VALUE1 = 0.475;
					const float OUTLINE_MAX_VALUE0 = 0.475;
					const float OUTLINE_MAX_VALUE1 = 0.525;

					float factorA = 1.0 - smoothstep(0.8, 1.0, alpha); // step(0.75, alpha.a);
					float detailA = factorA * baseColor.a;
					float a = detailA * alpha + (1.0 - factorA) * alpha;

					const float4 OUTLINE_COLOR = outlineColor;
					const float4 OUTLINE_COLOR2 = outlineColor;

					float4 transparent = OUTLINE_COLOR;
					transparent.a = 0.0;

					baseColor.a = 1.0;
					oColor = baseColor;

					if (a < OUTLINE_MAX_VALUE1) {
						// outlining
						if (a > OUTLINE_MIN_VALUE0 && a < OUTLINE_MAX_VALUE1) {
							float factor = 1.0;
							if (a < OUTLINE_MIN_VALUE1) {
								factor = smoothstep(OUTLINE_MIN_VALUE0, OUTLINE_MIN_VALUE1, a);
								oColor = lerp(transparent, OUTLINE_COLOR, factor);
							}
							else {
								factor = smoothstep(OUTLINE_MAX_VALUE1, OUTLINE_MAX_VALUE0, a);
								oColor = lerp(baseColor, OUTLINE_COLOR2, factor);
							}
						}
						else {
							oColor.a = 0.0;
						}
					}

					return oColor;
				}

				fixed4 alphaOutline(fixed alpha, fixed4 baseColor, fixed4 outlineColor, fixed4 current) {
					const fixed low = 0.155;
					const fixed lowUp = 0.8;
					const fixed hiLow = 0.85;
					const fixed hi = 0.2;
					const fixed bl = 0.5;

					fixed factor = step(low, alpha) * step(alpha, hi);
					alpha = step(low, alpha);
					return factor * ((1-bl)*current + outlineColor) + (1-factor) *((1-alpha)*current + alpha * baseColor ) ;
				}

				fixed4 splatOutlineBlend(fixed4 current, sampler2D decalMap, fixed2 uv, fixed alpha, float4 outlineColor) {
					//const fixed4 outlineColor = fixed4(0, 0, 0, 1); 

					fixed4 color = tex2D(decalMap, uv);
					//fixed4 outlined = alphaOutline(alpha, col, outlineColor, current);
					fixed4 outlined = alphaOutline2(alpha, color, outlineColor, current);
					//return outlined;
					return (1.0 - outlined.a) * current + outlined.a * outlined;
				}
				uniform float4 _outlineColor2;
				uniform float4 _outlineColor3;
				uniform float4 _outlineColor4;
				uniform float4 _outlineColor5;

				void SplatmapMix2(Input IN, out half4 splat_control, out fixed4 mixedDiffuse)
				{
					splat_control = tex2D(_Control, IN.tc_Control);

					fixed4 mainCol = tex2D(_FuckTex, IN.tc_Control);
					mixedDiffuse = mainCol;

					mixedDiffuse = splatAlphaBlend(mixedDiffuse, _Splat0, IN.uv_Splat0, splat_control.r);
					//mixedDiffuse = splatAlphaBlend(mixedDiffuse, _Splat1, IN.uv_Splat1, splat_control.g);

					//mixedDiffuse = splatOutlineBlend(mixedDiffuse, _Splat0, IN.uv_Splat0, splat_control.r, _outlineColor2);
					mixedDiffuse = splatOutlineBlend(mixedDiffuse, _Splat1, IN.uv_Splat1, splat_control.g, _outlineColor3);

					mixedDiffuse = splatOutlineBlend(mixedDiffuse, _Splat2, IN.uv_Splat2, splat_control.b, _outlineColor4);
					mixedDiffuse = splatOutlineBlend(mixedDiffuse, _Splat3, IN.uv_Splat3, splat_control.a, _outlineColor5);

					mixedDiffuse.a = 1;
				}


				void surf(Input IN, inout SurfaceOutput2 o)
				{
					half4 splat_control;
					fixed4 mixedDiffuse;
					SplatmapMix2(IN, splat_control, mixedDiffuse);

					o.Albedo = mixedDiffuse.rgb;
					o.Alpha = mixedDiffuse.a;
				}

				uniform float4 _isolineParams;
				sampler2D _gradientMap;
				uniform float4 _ambientLightColor;


				sampler2D _shadowMap;

				//uniform float inverseShadowmapSize;
				uniform float fixedDepthBias;
				uniform float gradientClamp;
				uniform float gradientScaleBias;
				uniform float4 shadowColor;



				
				fixed4 frag_surf (v2f_surf IN) : SV_Target {
				  // prepare and unpack data
				  Input surfIN;
				  UNITY_INITIALIZE_OUTPUT(Input,surfIN);
				  surfIN.uv_Splat0.x = 1.0;
				  surfIN.uv_Splat1.x = 1.0;
				  surfIN.uv_Splat2.x = 1.0;
				  surfIN.uv_Splat3.x = 1.0;
				  surfIN.tc_Control.x = 1.0;
				  surfIN.uv_Splat0 = IN.pack0.xy;
				  surfIN.uv_Splat1 = IN.pack0.zw;
				  surfIN.uv_Splat2 = IN.pack1.xy;
				  surfIN.uv_Splat3 = IN.pack1.zw;
				  surfIN.tc_Control = IN.custompack0.xy;
			      fixed3 lightDir = _WorldSpaceLightPos0.xyz;

				  SurfaceOutput2 o = (SurfaceOutput2)0;

				  o.Albedo = 0.0;
				  o.Alpha = 0.0;

				  surf (surfIN, o);
				  fixed4 result = fixed4(o.Albedo, o.Alpha);

				  float2 height = IN.outAlphaUVAndHeight.zw;
				  float occurence = _isolineParams.x; //2.0;
				  float a = tex2D(_gradientMap, float2(0.0, height.x * occurence)).r;
				  float4 lineColor = float4(1.0, 1.0, 1.0, 1.0) * (_isolineParams.y * (-1.0));

				  const float ambientModifier = 1.0;
				  
				  result = result * _ambientLightColor + result * (IN.outDiffuseLightColor
				    * inShadow(IN.pos, IN.shadowUV, _shadowMap, inverseShadowmapSize, fixedDepthBias, gradientClamp, gradientScaleBias, shadowColor.a));
				  
				  //result = IN.outDiffuseLightColor;
				  //float4 alphaColor = tex2D(_Control, IN.outAlphaUVAndHeight.xy);

				  const float MIN = 0.98;
				  const float MAX = 0.99;
				  float factor = 1.0 - (height.y - MIN) / (MAX - MIN);
				  factor = saturate(factor);
				  a = a * factor;

				  result += a * lineColor;
				  result.a = 1.0;

				 
				  /*
				  //设置shadowMap 使用depth 足够
				  //float4 shadowUV = IN.shadowUV / IN.shadowUV.w;
				  float4 shadowUV = IN.shadowUV;
				  //-1 1 shadowUV 范围
				  //x y z 方向上都是 -1 到1 并且 camera的projectionMatrix z方向 和 unity方向相反  0 最远位置 1 最近位置
				  shadowUV = shadowUV / 2 + 0.5;
				  float shadowIndencity = tex2D(_shadowMap, shadowUV.xy).x;
				  result.xyz = float3(shadowIndencity, shadowIndencity, shadowIndencity);
				  result.xyz = float3(shadowUV.z, shadowUV.z, shadowUV.z);
				  result.a = 1;
				  */

				  return result;
				}
				ENDCG
			}

		}

	}

}
